<script lang="ts">
	import {
		addServer as addServerCommand,
		removeServer as removeServerCommand,
		retryConnection,
	} from "$api/servers.remote";
	import { invalidateAll } from "$app/navigation";
	import { resolve } from "$app/paths";
	import Panel from "$lib/components/Panel.svelte";
	import TooltipTable from "$lib/components/TooltipTable.svelte";
	import { notificationStore } from "$lib/stores/notifications.svelte";
	import { formatBytes, serverName } from "$lib/utils/filters";
	import { SvelteSet } from "svelte/reactivity";
	import type { PageData } from "./$types";

	let { data }: { data: PageData } = $props();

	type Server = PageData["servers"][number];

	let adding = $state(false);
	let newServer = $state("");
	let loading = $state(false);
	let showRemoveModal = $state(false);
	let serverToRemove: Server | null = null;
	const retryingServers = new SvelteSet<string>();

	async function addServer() {
		if (!newServer) return;

		loading = true;
		try {
			await addServerCommand({ url: newServer });
			newServer = "";
			adding = false;
			notificationStore.notifySuccess("Server added successfully");
			// Reload the page to get updated servers
			await invalidateAll();
		} catch (error) {
			notificationStore.notifyError(error, "Failed to add server");
		} finally {
			loading = false;
		}
	}

	function openRemoveModal(server: Server) {
		serverToRemove = server;
		showRemoveModal = true;
	}

	function closeRemoveModal() {
		showRemoveModal = false;
		serverToRemove = null;
	}

	async function confirmRemove() {
		if (!serverToRemove) return;

		try {
			await removeServerCommand(serverToRemove.name);
			notificationStore.notifySuccess("Server removed successfully");
			closeRemoveModal();
			// Reload the page to get updated servers
			await invalidateAll();
		} catch (error) {
			notificationStore.notifyError(error, "Failed to remove server");
		}
	}

	function handleKeyDown(e: KeyboardEvent) {
		if (e.key === "Escape") {
			closeRemoveModal();
		}
	}

	async function retryServerConnection(server: Server) {
		retryingServers.add(server._id);

		try {
			await retryConnection(server._id);
			notificationStore.notifySuccess("Connection restored successfully");
			await invalidateAll();
		} catch (error) {
			notificationStore.notifyError(error, "Failed to retry connection");
		} finally {
			retryingServers.delete(server._id);
		}
	}
</script>

<svelte:window on:keydown={handleKeyDown} />

<Panel title="Servers">
	{#snippet actions()}
		<button class="btn btn-default btn-sm" onclick={() => (adding = !adding)}>
			{adding ? "Cancel" : "Add Server"}
		</button>
		{#if adding}
			<input
				type="text"
				placeholder="mongodb://user:password@hostname:port?directConnection=true"
				bind:value={newServer}
				disabled={loading}
				class="form-input"
			/>
			<button class="btn btn-outline-success btn-sm" onclick={addServer} disabled={!newServer.length || loading}>
				Add
			</button>
		{/if}
	{/snippet}

	<table class="table">
		<thead>
			<tr>
				<th>Name</th>
				<th>Databases</th>
				<th>Size</th>
				<th></th>
			</tr>
		</thead>
		<tbody>
			{#if data.servers && data.servers.length > 0}
				{#each data.servers as server (server._id)}
					<tr class="group">
						<td>
							{#await server.details}
								<span>
									{serverName(server.name)}
								</span>
							{:then details}
								{#if "error" in details && details.error}
									<span class="error">
										<span class="badge badge-danger" title={details.error.message}>Error</span>
										{serverName(server.name)}
									</span>
								{:else}
									<a href={resolve(`/servers/${encodeURIComponent(serverName(server.name))}/databases`)}>
										{serverName(server.name)}
									</a>
								{/if}
							{/await}
						</td>
						<td>
							{#await server.details}
								<span style="color: var(--text-secondary);">...</span>
							{:then details}
								{#if "databases" in details && details.databases}
									<TooltipTable
										columns={[
											{ header: "Database", key: "name" },
											{ header: "Collections", key: "collections" },
											{ header: "Size", key: "size" },
										]}
										rows={details.databases.map((db) => ({
											name: db.name,
											collections: db.collections,
											size: formatBytes(db.size),
										}))}
									>
										{details.databases.length}
									</TooltipTable>
								{/if}
							{/await}
						</td>
						<td>
							{#await server.details}
								<span style="color: var(--text-secondary);">...</span>
							{:then details}
								{#if "size" in details && details.size !== undefined}
									{formatBytes(details.size)}
								{/if}
							{/await}
						</td>
						<td style="width: 250px">
							<div class="flex gap-2 justify-end">
								{#await server.details then details}
									{#if "error" in details && details.error}
										<button
											class="btn btn-default btn-sm -my-2 hidden group-hover:inline"
											onclick={() => retryServerConnection(server)}
											disabled={retryingServers.has(server._id)}
										>
											{retryingServers.has(server._id) ? "Retrying..." : "Retry"}
										</button>
									{/if}
								{/await}
								<button
									class="btn btn-outline-danger btn-sm -my-2 hidden group-hover:inline"
									onclick={() => openRemoveModal(server)}
								>
									Remove from list
								</button>
							</div>
						</td>
					</tr>
				{/each}
			{:else}
				<tr>
					<td colspan="4">
						<div class="text-center">No servers...</div>
					</td>
				</tr>
			{/if}
		</tbody>
	</table>
</Panel>

{#if showRemoveModal}
	<!-- svelte-ignore a11y_click_events_have_key_events -->
	<!-- svelte-ignore a11y_no_static_element_interactions -->
	<div class="modal-overlay" onclick={closeRemoveModal}>
		<div class="modal" onclick={(e) => e.stopPropagation()}>
			<div class="modal-body">
				<p>
					Are you sure you want to remove this server? This will only remove it from this list. You can add it back.
				</p>
			</div>
			<div class="modal-footer">
				<button class="btn btn-default btn-sm" onclick={closeRemoveModal}>No</button>
				<button class="btn btn-outline-danger btn-sm" onclick={confirmRemove}>Yes</button>
			</div>
		</div>
	</div>
{/if}

<style lang="postcss">
	input[type="text"] {
		min-width: 400px;
	}
</style>
